package com.qianfeng.openapi.web.master.service.impl;

import com.qianfeng.openapi.web.master.bean.LayUITableVO;
import com.qianfeng.openapi.web.master.bean.LayUITreeVO;
import com.qianfeng.openapi.common.enums.OpenApiEnums;
import com.qianfeng.openapi.common.exception.OpenApiEx;
import com.qianfeng.openapi.web.master.mapper.MenuMapper;
import com.qianfeng.openapi.web.master.pojo.Menu;
import com.qianfeng.openapi.web.master.service.MenuService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

@Service
@Slf4j
public class MenuServiceImpl implements MenuService {

    @Resource
    private MenuMapper menuMapper;


    @Override
    public List<Menu> findLeftSideNav(Integer userId) {
        //1. 调用mapper,查询type=1和type=0的菜单信息,并且按照SORT做升序排序
        List<Menu> menuList = menuMapper.findLeftSideNavMenu(userId);

        //2. 将数据进行封装
        List<Menu> data = this.getData(menuList);

        //3. 返回数据
        return data;
    }

    @Override
    public List<Menu> findAll() {
        return menuMapper.findAll();
    }

    @Override
    public LayUITableVO findMenuTableVO() {
        //1. 查询数据总条数
        Long count = menuMapper.findCount();
        //2. 查询全部的菜单数据,排序
        List<Menu> menus = menuMapper.findAll();

        //3. 将菜单信息分类封装到一个Map<Integer,Menu> levelOne
        Map<Integer,Menu> levelOne = new LinkedHashMap<>();
        Map<Integer,Menu> levelTwo = new HashMap<>();
        for (Menu menu : menus) {
            if(menu.getParentId() == null){
                // 一级菜单
                levelOne.put(menu.getId(),menu);
            }else{
                if(menu.getType() == 1) {
                    // 二级菜单(不是按钮)
                    levelTwo.put(menu.getId(),menu);
                    levelOne.get(menu.getParentId()).getChildren().add(menu);
                }else{
                    // 三级菜单
                    Menu twoMenu = levelTwo.get(menu.getParentId());
                    if(twoMenu != null){
                        twoMenu.getChildren().add(menu);
                        continue;
                    }
                    // 二级菜单(按钮)
                    levelOne.get(menu.getParentId()).getChildren().add(menu);
                }
            }
        }

        //4. 遍历levelOne，封装为List<Menu> data
        List<Menu> data = new ArrayList<>();
        for (Map.Entry<Integer, Menu> entry : levelOne.entrySet()) {
            Menu menu = entry.getValue();
            this.addMenuToData(data,menu);
        }

        //5. 封装LayUITableVO
        LayUITableVO result = new LayUITableVO();
        result.setCount(count);
        result.setData(data);

        //6. 返回
        return result;
    }

    @Override
    public List<LayUITreeVO> findMenuTreeVO() {
        //1. 调用mapper查询树结构
        List<Menu> menuList = menuMapper.findAllByTypeZeroToOne();

        //2. 封装数据到List<LayUITreeVO>
        List<LayUITreeVO> data = new ArrayList<>();
        Map<Integer,LayUITreeVO> levelOne = new LinkedHashMap<>();
        for (Menu menu : menuList) {
            // 如果是一级菜单,就封装为LayUITreeVO并添加到levelOne的Map集合里
            if(menu.getParentId() == null){
                LayUITreeVO vo = new LayUITreeVO(menu.getId(),menu.getName());
                levelOne.put(vo.getId(),vo);
            }else{
                LayUITreeVO vo = new LayUITreeVO(menu.getId(),menu.getName());
                levelOne.get(menu.getParentId()).getChildren().add(vo);
            }
        }
        // 将levelOne封装为data
        for (Map.Entry<Integer, LayUITreeVO> entry : levelOne.entrySet()) {
            data.add(entry.getValue());
        }
        //3. 返回
        return data;
    }

    @Override
    @Transactional
    public void add(Menu menu) {
        //1. 调用mapper执行添加
        int count = menuMapper.insertSelective(menu);

        //2. 判断count
        if(count != 1){
            log.error("【菜单模块添加】 添加菜单信息失败！！menu = {}",menu);
            throw new OpenApiEx(OpenApiEnums.MENU_ADD_ERROR);
        }

    }

    @Override
    public List<Menu> findMenuListByUserId(Integer userId) {
        return menuMapper.findByUserId(userId);
    }

    // 递归将map中的数据封装到List集合中
    private void addMenuToData(List<Menu> data,Menu menu){
        //1. 将分类插入到data中
        data.add(menu);
        //2.1 判断是否有子节点
        List<Menu> children = menu.getChildren();
        if(children != null && children.size() > 0) {
            //2.2 调用当前方法,插入内容
            for (Menu child : children) {
                this.addMenuToData(data,child);
            }
        }
    }

    // 将MenuList封装为左侧导航需要的效果
    private List<Menu> getData(List<Menu> menuList) {
        //1. 创建Map<Integer,Menu> 作为map,暂时存放数据
        Map<Integer,Menu> map = new LinkedHashMap<>();
        //2. 遍历menuList
        for (Menu menu : menuList) {
            //2.1 将menuList中parentId为null的Menu对象,将id作为key,Menu对象作为value存储到map里
            if(menu.getParentId() == null){
                map.put(menu.getId(),menu);
            }else{
                //2.2 将parentId不为null的直接插入到指定Menu的children属性中
                map.get(menu.getParentId()).getChildren().add(menu);
            }
        }
        //3. 将Map转为List,返回
        List<Menu> data = new ArrayList<>();
        for (Map.Entry<Integer, Menu> entry : map.entrySet()) {
            data.add(entry.getValue());
        }
        return data;
    }
}
